#include "CameraManager.h"
//#include "DX11InputManager.h"
#include "Timer.h"
#include "D3DXVECTOROperators.h"
#include "DX11HelpfulFunctions.h"
#include "StringUtilities.h"
#include "Game.h"

#include <math.h>
#include <WinUser.h>

CameraManager::CameraManager()
{
	m_pos = D3DXVECTOR3(0.0f, 0.0f, -10.0f);
	m_target = D3DXVECTOR3(0.01f, 0.0f, 0.01f);
	m_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	m_miniMapPos = D3DXVECTOR3(0.0f, 20.0f, -10.0f);	
	m_vel = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_angleV = 1.6319839f;
	m_angleH = 0.010237293f;
	m_mouseLeftDown = false;
	m_rotAngle = 0;
	m_zoom =  0.0f;
	m_zoomVel = 0.0f;

	m_xRot = 0;
	m_yRot = 0;
	m_zRot = 0;

	m_moveAcc = 0.0f;
	m_moveVel = 0.0f;

	m_wKeyDown = false;
	m_aKeyDown = false;
	m_sKeyDown = false;
	m_dKeyDown = false;
	m_pgUpKeyDown = false;
	m_pgDownKeyDown = false;

	m_lMouseButtonDown = false;
	m_rMouseButtonDown = false;
	m_mouseWheelDelta = 0.0f;

	TheEventPoller::Instance()->AddHandler(this);
	m_radi = D3DXVECTOR3(3.0f, 3.0f, 3.0f);
	for (int i = 0; i != 10; i++)
	{
		m_screenPos.push_back(Text());
	}
	
	m_drawCol = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);
}

CameraManager::~CameraManager()
{
	TheEventPoller::Instance()->RemoveHandler(this);
}

void CameraManager::Draw()
{
}

void CameraManager::Update()
{
	UpdateMain();	
}

void CameraManager::UpdateMain()
{
	//m_keyboardState = TheDX11InputManager::Instance()->GetKeyPressed();
	//m_mouseState = TheDX11InputManager::Instance()->GetMouseState();

	m_moveAcc = 0.25f * TheTimer::Instance()->GetDt();
	float mouseMoveSpeed = TheTimer::Instance()->GetDt();
	float dt = TheTimer::Instance()->GetDt();


	// mouse checks
	// mouse motions


	float moveAmountX = 0;
	float moveAmountZ = 0;

		// mouse zoom
	m_zoomVel -= m_mouseWheelDelta * dt * 1.0001f;


	m_mouseWheelDelta *= (5.0f * dt);
	LimitCameraMovements();

	// keyboard checks
	if (m_pgUpKeyDown)
	{
		m_zoomVel -= 2.5f * dt;
	}
	else if (m_pgDownKeyDown)
	{
		m_zoomVel += 2.5f * dt;
	}
	
	//if (m_aKeyDown)
	//{
	//	moveAmountX += sin(m_angleV + (float)M_PI) * sin(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;
	//	moveAmountZ += sin(m_angleV + (float)M_PI) * cos(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;

	//	//moveAmountX -= sin(m_angleH) * sin(m_angleV) * m_moveAcc * 2.0f;
	//	//moveAmountZ -= sin(m_angleH) * cos(m_angleV) * m_moveAcc * 2.0f;
	//	//m_vel -= D3DXVECTOR3(moveAmountX, 0, moveAmountZ);

	//}
	//if (m_dKeyDown)
	//{
	//	moveAmountX -= sin(m_angleV + (float)M_PI) * sin(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;
	//	moveAmountZ -= sin(m_angleV + (float)M_PI) * cos(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;
	//	//m_vel += D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//	//moveAmountX += sin(m_angleH) * sin(m_angleV) * m_moveAcc * 2.0f;
	//	//moveAmountZ += sin(m_angleH) * cos(m_angleV) * m_moveAcc * 2.0f;
	//}
	//if (m_sKeyDown)
	//{
	//	moveAmountX -= sin(m_angleV) * sin(m_angleH) * m_moveAcc * 2.0f;
	//	moveAmountZ -= sin(m_angleV) * cos(m_angleH) * m_moveAcc * 2.0f;
	//	//m_vel += D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//}
	//if (m_wKeyDown)
	//{
	//	moveAmountX += sin(m_angleV) * sin(m_angleH) * m_moveAcc * 2.0f;
	//	moveAmountZ += sin(m_angleV) * cos(m_angleH) * m_moveAcc * 2.0f;
	//	//m_vel -= D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//}


	m_vel -= D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	// set target to picked position
	m_zoom += m_zoomVel;
	if (m_zoom < 2.0f)
	{
		m_zoom = 2.0f;
	}
	m_pos += m_vel;
	m_target = D3DXVECTOR3(
		sin(m_angleV) * sin(m_angleH) * m_zoom, 
		cos(m_angleV) * m_zoom, 
		sin(m_angleV) * cos(m_angleH) * m_zoom 
		);

	//D3DXVec3Mult(&m_vel, D3DXVECTOR3(0.9f, 0.9f, 0.9f));
		m_target = D3DXVECTOR3(0.0f, 0.0f, -20.0f);
	D3DXMatrixLookAtLH(&m_view, &D3DXVECTOR3(m_target + m_pos), &m_pos, &m_up);

	TheScreenManager::Instance()->SetViewMatrix(m_view);
	
	m_zoomVel *= 0.9f;
	m_vel *= 0.9f;

}

float CameraManager::GetCameraRotation() const
{
	return m_angleH;
}

void CameraManager::UpdateMiniMap()
{
	float dt = TheTimer::Instance()->GetDt();
	
	D3DXMATRIX result;
	//m_miniMapPos.x = m_pos.x;
	//m_miniMapPos.z = m_pos.z;

	D3DXVECTOR3 target;
	D3DXVec3Normalize(&target, &m_target);
	target.y = 100.0f;

	m_miniMapPos.x = 0.0f;
	m_miniMapPos.y = 300.0f;
	m_miniMapPos.z = -10.0f;

	target.x = 0.0f;
	target.y = 100.00000f;
	target.z = 0.99812734f;

	D3DXMatrixLookAtLH(&result, &D3DXVECTOR3(m_miniMapPos + target), 
		&m_miniMapPos, 
		&m_up);
	
	TheScreenManager::Instance()->SetBEV(result);
}

void CameraManager::UpdateHUD()
{
	D3DXMATRIX result;
	D3DXVECTOR3 pos(0.0f, 0.0f, 0.0f);

	D3DXVECTOR3 target;
	D3DXVec3Normalize(&target, &m_target);
	target.y = 100.0f;

	//m_miniMapPos.x = 0.0f;
	//m_miniMapPos.y = 3000.0f;
	//m_miniMapPos.z = -10.0f;

	target.x = 0.0f;
	target.y = 100.00000f;
	target.z = 0.99812734f;

	D3DXMatrixLookAtLH(&result, &D3DXVECTOR3(pos + target), 
		&pos, 
		&m_up);
	
	TheScreenManager::Instance()->SetBEV(result);
}

void CameraManager::SetCameraPos(const D3DXVECTOR3& pos)
{
	m_pos = pos;
}

void CameraManager::GenerateReflectedMatrix()
{
	// change functions parameters so that it takes in a target
	D3DXVECTOR3 reflectedTarget = D3DXVECTOR3(0.01f, 0.0f, 0.1f);
	D3DXVECTOR3 pos = D3DXVECTOR3(	(sin((float)-M_PI) * sin(0.0f) * m_zoom), 
		(cos((float)-M_PI) * m_zoom), 
		(sin((float)-M_PI) * cos(0.0f) * m_zoom));

	D3DXMatrixLookAtLH(&m_reflectedView, &D3DXVECTOR3(0.0f, -1.0f, 0.0f), &reflectedTarget, &m_up);
}

void CameraManager::SetReflectedMatrix()
{
	TheScreenManager::Instance()->SetViewMatrix(m_reflectedView);
}

void CameraManager::SetBirdsEyeViewMatrix()
{
	D3DXMATRIX result;
	m_miniMapPos.x = m_pos.x;
	m_miniMapPos.z = m_pos.z;
	D3DXVECTOR3 target(-0.00005627f, 60.000000f, -1.21489796f);
	//D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMatrixLookAtLH(&result, &D3DXVECTOR3(m_pos + D3DXVECTOR3(m_target.x, 60.0f, m_target.z)), &m_pos, &m_up);
	TheScreenManager::Instance()->SetBEV(result);
}

void CameraManager::SetBaseMatrix()
{
	TheScreenManager::Instance()->SetViewMatrix(m_view);
}

void CameraManager::LimitCameraMovements()
{
	if (m_zoom > 500.0f)
	{
		m_zoom = 500.0f;
	}
}

const D3DXVECTOR3& CameraManager::GetCameraPos() const
{
	return m_pos;
}

void CameraManager::AddEventHandler()
{
	TheEventPoller::Instance()->AddHandler(this);
}

void CameraManager::RemoveEventHandler()
{
	TheEventPoller::Instance()->RemoveHandler(this);
}

void CameraManager::OnKeyDownEvent(const WPARAM& event)
{		
	if (event == VK_UP)
	{
		m_pgUpKeyDown = true;
	}
	else if (event == VK_DOWN)
	{
		m_pgDownKeyDown = true;
	}

	char c = MapVirtualKey(event, MAPVK_VK_TO_CHAR);

	//m_moveAcc = 0.1f * TheTimer::Instance()->GetDt();
	if(c == 'A')
	{
		m_moveVel += m_moveAcc;
		m_aKeyDown = true;
	}
	if(c == 'D')
	{
		m_moveVel += m_moveAcc;
		m_dKeyDown = true;
	}
	if(c == 'W')
	{
		m_moveVel += m_moveAcc;
		m_wKeyDown = true;
	}
	if(c == 'S')
	{
		m_moveVel += m_moveAcc;
		m_sKeyDown = true;
	}
	if(c == 'R')
	{
		m_angleH = -2.4f;
	}
	if(c == 'Z')
	{
		m_zKeyDown = true;
	}
	if(c == 'X')
	{
		m_xKeyDown = true;
	}
}

void CameraManager::OnKeyUpEvent(const WPARAM& event)
{	
	if (event == VK_UP)
	{
		m_pgUpKeyDown = false;
	}
	else if (event == VK_DOWN)
	{
		m_pgDownKeyDown = false;
	}


	char c = MapVirtualKey(event, MAPVK_VK_TO_CHAR);

	if(c == 'A')
	{
		m_aKeyDown = false;
	}
	if(c == 'D')
	{
		m_dKeyDown = false;
	}
	if(c == 'W')
	{
		m_wKeyDown = false;
	}
	if(c == 'S')
	{
		m_sKeyDown = false;
	}
	if(c == 'Z')
	{
		m_zKeyDown = false;
	}
	if(c == 'X')
	{
		m_xKeyDown = false;
	}
}

void CameraManager::OnMouseMotionEvent(const LPARAM& event)
{
	float differenceH = 0.0f;
	float differenceV = 0.0f;

	int x = LOWORD(event);
	int y = HIWORD(event);

	bool mouseInBoundsX = false;
	bool mouseInBoundsY = false;

	int screenWidth = TheScreenManager::Instance()->GetWindowWidth();
	int screenHeight = TheScreenManager::Instance()->GetWindowHeight();

	if (x <= screenWidth && x >= 0)
	{
		//m_mouseX = x;
		mouseInBoundsX = true;
	}
	if (y <= screenHeight && y >= 0)
	{
		//m_mouseY = y;
		mouseInBoundsY = true;
	}

	if (m_lMouseButtonDown && mouseInBoundsX && mouseInBoundsY)
	{
		differenceH = m_currentMouseX - (float)x;
		differenceV = m_currentMouseY - (float)y;

		m_currentMouseX = (float)x;
		m_currentMouseY = (float)y;

		differenceH /= 8.0f;
		differenceV /= 8.0f;

		differenceH *= (float)(D3DX_PI / 180.0f);
		differenceV *= (float)(D3DX_PI / 180.0f);

		m_angleH += differenceH;
		m_angleV -= differenceV;
	}
}

void CameraManager::OnMouseButtonDownEvent(const MSG& event)
{
	// left mouse button down

	if (event.message == WM_LBUTTONDOWN)
	{
		m_currentMouseX = LOWORD(event.lParam);
		m_currentMouseY = HIWORD(event.lParam);
		m_lMouseButtonDown = true;
	}
	else if (event.message == WM_RBUTTONDOWN)
	{
		m_rMouseButtonDown = true;
		//D3DXVECTOR3 mousePos = DX11::Get3DMousePos(D3DXVECTOR2(m_currentMouseX, m_currentMouseY));
		float t = 0;
	}
}

void CameraManager::OnMouseButtonUpEvent(const MSG& event)
{
	// left mouse button up
	if (event.message == WM_LBUTTONUP)
	{
		m_lMouseButtonDown = false;
	}
	else if (event.message == WM_RBUTTONUP)
	{
		m_rMouseButtonDown = false;
	}
}

void CameraManager::OnMouseWheelEvent(const WPARAM& event)
{
	m_mouseWheelDelta = GET_WHEEL_DELTA_WPARAM(event);
	if (m_mouseWheelDelta < 0)
	{
		//m_pgDownKeyDown = true;
		m_mouseWheelDelta = -10.0f;
	}
	else
	{
		m_mouseWheelDelta = 10.0f;
		//m_pgUpKeyDown = true;
	}
}